package com.pan.note.im.service;

import com.pan.note.im.dto.GameDataDto;
import com.pan.note.im.netty.NettyWebSocketHandler;
import com.pan.note.im.util.GameDataContext;
import lombok.extern.slf4j.Slf4j;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 游戏数据处理服务
 */
@Slf4j
public class SnakeDataProcessService {

    public static ConcurrentHashMap<String,String> playerDir = new ConcurrentHashMap<>();
    public static ConcurrentHashMap<String,Boolean> playerIsStart = new ConcurrentHashMap<>();

    /**
     * 开始游戏方法，新建一个线程处理游戏数据
     * @param player1Id 一号玩家id
     * @param player2Id 二号玩家id
     */
    public static void startGame(String player1Id,String player2Id){
        new Thread(()->{
            Random random = new Random();
            List<GameDataDto> players = new ArrayList<>();
            List<Integer> foodInit = new ArrayList<>();
            foodInit.add(100);
            foodInit.add(200);
            players.add(initGameData(player1Id,0));
            players.add(initGameData(player2Id,1));
            GameDataContext.setPlayer(players);
            GameDataContext.setFood(foodInit);
            GameDataContext.setIsStart(true);
            playerDir.put(player1Id,"d");
            playerDir.put(player2Id,"d");
            playerIsStart.put(player1Id,true);
            playerIsStart.put(player2Id,true);
            while (true){
                /**
                 * 游戏流程
                 * 1.先获取到两个玩家到数据
                 * 2.根据playerDir对线程中对方向赋值
                 * 3.计算蛇的运动
                 * 4.将最新的数据重新存入ThreadLocal中，同时发送给前端
                 * 5.循环上述操作
                 */
                // 获取玩家数据
                List<GameDataDto> gameDataDtos = GameDataContext.getPlayer();
                if (!playerIsStart.get(player1Id)||!playerIsStart.get(player2Id)){
                    GameDataContext.setIsStart(false);
                }
                if (!GameDataContext.getIsStart()){
                    GameDataContext.removePlayer();
                    break;
                }
                // 获取食物数据
                List<Integer> food = GameDataContext.getFood();
                // 根据玩家id修改对应蛇的运动方向
                gameDataDtos.stream().filter(dto -> dto.getPlayerId().equals(player1Id)).forEach(e -> e.setDir(playerDir.get(player1Id)));
                gameDataDtos.stream().filter(dto -> dto.getPlayerId().equals(player2Id)).forEach(e -> e.setDir(playerDir.get(player2Id)));
                // 计算蛇的运动
                actionPerformed(gameDataDtos,food,random);
                // 将最新结果重新存入ThreadLocal中
                GameDataContext.setPlayer(gameDataDtos);
                // 调用netty中的静态方法，向前端发送数据
                NettyWebSocketHandler.sendGameData(gameDataDtos,food);
                log.info("游戏数据{}",gameDataDtos);
                try {
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

    public static GameDataDto initGameData(String playerId,Integer init){
        GameDataDto gameDataDto = new GameDataDto();
        Integer[] snakeX = new Integer[10];
        Integer[] snakeY = new Integer[10];
        Integer[] random = {100,500};
        //初始化开始的蛇,给蛇定位,
        snakeX[0] = 100; snakeY[0] = random[init];
        snakeX[1] = 75; snakeY[1] = random[init];
        snakeX[2] = 50; snakeY[2] = random[init];
        gameDataDto.setPlayerId(playerId);
        gameDataDto.setDir("d");
        gameDataDto.setLenth(3);
        gameDataDto.setSnakeX(snakeX);
        gameDataDto.setSnakeY(snakeY);
        return gameDataDto;
    }

    public static void actionPerformed(List<GameDataDto> dtoList,List<Integer> food,Random random) {
        for (GameDataDto dto : dtoList) {
            Integer[] snakeX = dto.getSnakeX();
            Integer[] snakeY = dto.getSnakeY();
            Integer lenth = dto.getLenth();
            Integer score = dto.getScore();
            //右移:即让后一个移到前一个的位置即可 !
            for (int i = lenth-1; i > 0; i--) { //除了脑袋都往前移：身体移动
                snakeX[i] = snakeX[i-1]; //即第i节(后一节)的位置变为(i-1：前一节)节的位置！
                snakeY[i] = snakeY[i-1];
            }
            //通过方向控制，头部移动
            if (dto.getDir().equals("d")){
                snakeX[0] = snakeX[0]+25;
                if (snakeX[0]>1200) snakeX[0] = 25;
            }else if (dto.getDir().equals("a")){
                snakeX[0] = snakeX[0]-25;
                if (snakeX[0]<25) snakeX[0] = 1200;
            }else if (dto.getDir().equals("s")){
                snakeY[0] = snakeY[0]-25;
                if (snakeY[0]<75) snakeY[0] = 800;
            }else if (dto.getDir().equals("w")){
                snakeY[0] = snakeY[0]+25;
                if (snakeY[0]>800) snakeY[0] = 75;
            }
            //吃食物:当蛇的头和食物一样时,算吃到食物!
            if (snakeX[0]== food.get(0) && snakeY[0]== food.get(1)){
                //1.长度加一
                lenth++;
                //每吃一个食物，增加积分
                score = score + 10;
                //2.重新生成食物
                food.set(0,25 + 25* random.nextInt(34));
                food.set(1,75 + 25* random.nextInt(24));
                GameDataContext.setFood(food);
            }
        }
    }


}
